/****************************************************************************
 * @file    BitManipulation.h
 * @brief   A library for bit manipulation operations using macros.
 * @details This library provides macros for setting, clearing, toggling,
 *          and checking individual bits in an integer. It also supports
 *          bit fields, bit masks, and extracting bit values.
 *
 * @author  [Your Name]
 * @date    2024-08-30
 ****************************************************************************/

#ifndef BITMANIPULATION_H
#define BITMANIPULATION_H

#include <stdint.h>

/**
 * @brief Set a specific bit in an integer to 1.
 * @param[in,out] value The integer value where the bit will be set.
 * @param[in] bit The bit position to set (0-based).
 */
#define SET_BIT(value, bit) ((value) |= (1U << (bit)))

/**
 * @brief Clear a specific bit in an integer to 0.
 * @param[in,out] value The integer value where the bit will be cleared.
 * @param[in] bit The bit position to clear (0-based).
 */
#define CLEAR_BIT(value, bit) ((value) &= ~(1U << (bit)))

/**
 * @brief Toggle a specific bit in an integer.
 * @param[in,out] value The integer value where the bit will be toggled.
 * @param[in] bit The bit position to toggle (0-based).
 */
#define TOGGLE_BIT(value, bit) ((value) ^= (1U << (bit)))

/**
 * @brief Check if a specific bit is set.
 * @param[in] value The integer value to check.
 * @param[in] bit The bit position to check (0-based).
 * @return 1 if the bit is set, 0 otherwise.
 */
#define CHECK_BIT(value, bit) (((value) & (1U << (bit))) ? 1 : 0)

/**
 * @brief Set multiple bits in an integer to 1 using a bit mask.
 * @param[in,out] value The integer value where the bits will be set.
 * @param[in] mask The bit mask indicating which bits to set.
 */
#define SET_BITS(value, mask) ((value) |= (mask))

/**
 * @brief Clear multiple bits in an integer to 0 using a bit mask.
 * @param[in,out] value The integer value where the bits will be cleared.
 * @param[in] mask The bit mask indicating which bits to clear.
 */
#define CLEAR_BITS(value, mask) ((value) &= ~(mask))

/**
 * @brief Toggle multiple bits in an integer using a bit mask.
 * @param[in,out] value The integer value where the bits will be toggled.
 * @param[in] mask The bit mask indicating which bits to toggle.
 */
#define TOGGLE_BITS(value, mask) ((value) ^= (mask))

/**
 * @brief Check if all bits specified by a bit mask are set.
 * @param[in] value The integer value to check.
 * @param[in] mask The bit mask indicating which bits to check.
 * @return 1 if all bits specified by the mask are set, 0 otherwise.
 */
#define CHECK_BITS(value, mask) (((value) & (mask)) == (mask) ? 1 : 0)

/**
 * @brief Extract bits from a specific position with a bit mask.
 * @param[in] value The integer value to extract bits from.
 * @param[in] mask The bit mask indicating which bits to extract.
 * @return The extracted bits.
 */
#define EXTRACT_BITS(value, mask) ((value) & (mask))

/**
 * @brief Extract bits from a specific position and shift them to the right.
 * @param[in] value The integer value to extract bits from.
 * @param[in] mask The bit mask indicating which bits to extract.
 * @param[in] shift The number of positions to shift the extracted bits to the right.
 * @return The shifted extracted bits.
 */
#define EXTRACT_AND_SHIFT_BITS(value, mask, shift) (((value) & (mask)) >> (shift))

/**
 * @brief Insert bits into a specific position with a bit mask.
 * @param[in,out] value The integer value to insert bits into.
 * @param[in] bits The bits to insert.
 * @param[in] mask The bit mask indicating which bits to insert.
 */
#define INSERT_BITS(value, bits, mask) ((value) = ((value) & ~(mask)) | (((bits) << __builtin_ctz(mask)) & (mask)))

/**
 * @brief Get the number of bits in an integer.
 * @param[in] value The integer value.
 * @return The number of bits.
 */
#define GET_BITS_COUNT(value) (sizeof(value) * 8)

#endif // BITMANIPULATION_H
